package socket

import (
	"encoding/json"
	"fmt"
	"got/bytestream"
	"sync"
	"time"
)

//远程调用处理
const (
	//定义请求类型
	CLASS_REQUEST  int8 = 1 //请求
	CLASS_RESPONSE int8 = 2 //响应
)

var (
	//定义字节流请求头
	HEAD_DATA = [4]byte{88, 91, 10, 15}
)

//
type Any interface{}
type routerFunc func(*BtContext) Any
type callFunc func(*BtContext) error

//字节流socket路由
type BtContext struct {
	Class int8   //1请求，2路由
	Data  []byte //（请求or返回）的数据
	Path  string //（请求or返回）的路径
	Key   string //返回回调的key值
	Conn  *Conn  //conn的cache
}

//快速反序列化
func (this *BtContext) Unmarshal(a interface{}) error {
	return json.Unmarshal(this.Data, a)
}

//字节流路由
type RemoteCall struct {
	routerFuncs map[string]routerFunc //路由回调
	lockRouter  *sync.Mutex           //路由锁
	lockCall    *sync.Mutex           //回调锁
	callFuncs   map[string]callFunc   //请求回调
	btStream    *bytestream.ByteStream
	Conn        *Conn
	index       int64
}

func newRemoteCall(conn *Conn) *RemoteCall {
	o := new(RemoteCall)
	o.Conn = conn
	o.routerFuncs = make(map[string]routerFunc)
	o.callFuncs = make(map[string]callFunc)
	o.btStream = bytestream.NewByteStream(HEAD_DATA).UnPackCall(o.succHandle)
	o.lockRouter = new(sync.Mutex)
	o.lockCall = new(sync.Mutex)
	return o
}

//
func (this *RemoteCall) WriteStreams(bt []byte) {
	this.btStream.WriteStreams(bt)
}

//流
func (this *RemoteCall) succHandle(bt []byte) {
	var ctx *BtContext
	e := json.Unmarshal(bt, &ctx)
	if e != nil {
		return
	}
	ctx.Conn = this.Conn
	switch ctx.Class {
	//请求处理
	case CLASS_REQUEST:
		this.lockRouter.Lock()
		defer this.lockRouter.Unlock()
		if call, ok := this.routerFuncs[ctx.Path]; ok {
			res := call(ctx)
			reCtx := &BtContext{
				Class: CLASS_RESPONSE,
				Data:  this.makeBytes(res),
				Key:   ctx.Key,
			}
			bt, _ := json.Marshal(reCtx)
			bt = bytestream.Pack(HEAD_DATA, bt)
			this.Conn.Write(bt)
		}
	//请求响应返回处理
	case CLASS_RESPONSE:
		this.lockCall.Lock()
		defer this.lockCall.Unlock()
		if call, ok := this.callFuncs[ctx.Key]; ok {
			if e := call(ctx); e == nil {
				delete(this.callFuncs, ctx.Key)
			}
		}
	}
}

//转换为字节码，如果本来就是字节，则不进行转换,否则使用json序列化
func (this *RemoteCall) makeBytes(dt interface{}) []byte {
	if bt, ok := dt.([]byte); ok {
		return bt
	}
	data, e := json.Marshal(dt)
	if e != nil {
		panic("转换错误," + e.Error())
	}
	return data
}

//注册路由
func (this *RemoteCall) Reg(path string, call routerFunc) {
	this.lockRouter.Lock()
	defer this.lockRouter.Unlock()
	this.routerFuncs[path] = call
}

//异步远程回调
func (this *RemoteCall) Call(path string, arg interface{}, call callFunc) {
	this.lockCall.Lock()
	defer this.lockCall.Unlock()
	this.index++
	time.Sleep(time.Microsecond * 1)
	key := fmt.Sprint("ak", this.index)
	this.callFuncs[key] = call
	ctx := &BtContext{
		Class: CLASS_REQUEST,
		Data:  this.makeBytes(arg),
		Key:   key,
		Path:  path,
	}
	bt, e1 := json.Marshal(ctx)
	if e1 != nil {
		panic("请求正文错误," + e1.Error())
	}
	bt = bytestream.Pack(HEAD_DATA, bt)
	this.Conn.Write(bt)
}

//同步远程回调
func (this *RemoteCall) CallSync(path string, arg interface{}, call callFunc, wait time.Duration) bool {
	cc := make(chan bool)
	timeout := false
	this.Call(path, arg, func(c *BtContext) error {
		if timeout {
			return nil
		}
		ret := call(c)
		cc <- true
		return ret
	})
	res := false
	select {
	case res = <-cc:
	case <-time.After(wait):
		res = false
	}
	return res
}
